#include "spellbar.h"
#include "graphics.opengl/renderer.h"
#include "graphics/graphicsmanager.h"

#include "worldgridmanager.h"
#include "application.h"



namespace infinity {
	namespace render {

SpellBar::SpellBar(Container * container)
:	m_vertexFormat(NULL)
,	m_indexBuffer(NULL)
,	m_vertexBuffer(NULL)
,	m_root(NULL)
,	m_indexSelecteur(0)
,	m_container(container)
,	m_trianglesCount(0)
{
	dwAssert(container != NULL, "Invalid parameter: container is null");
}

SpellBar::~SpellBar()
{
	dw::graphics::Renderer& renderer = dw::graphics::GraphicsManager::getInstance().getRenderer();

	renderer.releaseIndexBuffer(m_indexBuffer);
	renderer.releaseVertexBuffer(m_vertexBuffer);

	delete m_vertexFormat;
	delete m_root;
}


void SpellBar::initializeGUI()
{
	const dw::system::Window& window = Application::getInstance().getWindow();

	dw::float32 offset = dw::float32(window.getWidth() - ((SlotsCount * SlotDimension) + (SlotsCount - 1) * SlotOffset)) / 2.0f;

	m_root = new Widget();
	m_root->setPosition(dw::maths::Vector2f(offset,0.0f));

	m_selecteur.setPosition(dw::maths::Vector2f(dw::float32(m_indexSelecteur * (SlotDimension + SlotOffset)), 0.0f));
	m_selecteur.setDimension(dw::maths::Vector2f(dw::float32(SlotDimension), dw::float32(SlotDimension)));
	m_selecteur.setImageUV(
		dw::maths::Vector2f(0.0f, 2.0f / 16.0f),
		dw::maths::Vector2f(1.0f / 16.0f, 3.0f / 16.0f));
	m_selecteur.setZOrder(Widget::LAYER_MIDDLE);

	m_root->addChild(& m_selecteur);


	for(dw::uint32 index = 0 ; index < SlotsCount ; ++index)
	{
		m_imagesBoxes[index].setPosition(dw::maths::Vector2f(dw::float32(index * (SlotDimension + SlotOffset)), 0.0f));
		m_imagesBoxes[index].setDimension(dw::maths::Vector2f(dw::float32(SlotDimension), dw::float32(SlotDimension)));
		m_imagesBoxes[index].setImageUV(
			dw::maths::Vector2f(0.0f, 0.0f),
			dw::maths::Vector2f(0.0f, 0.0f));
		m_imagesBoxes[index].setZOrder(Widget::LAYER_BACK);


		m_root->addChild(& m_imagesBoxes[index]);
	}


	createMesh();
}

void SpellBar::createMesh()
{
	dw::graphics::opengl::Renderer& renderer(static_cast< dw::graphics::opengl::Renderer& >(dw::graphics::GraphicsManager::getInstance().getRenderer()));

	using dw::graphics::VertexElement;

	static const VertexElement elements[] = {
		{ VertexElement::vec3, VertexElement::position, 0 },
		{ VertexElement::vec2, VertexElement::texcoord, 0 }
	};

	m_vertexFormat = new dw::graphics::VertexFormat(elements, 2);

	m_indexBuffer = renderer.createIndexBuffer(
		dw::graphics::IndexBuffer::update_often,
		dw::graphics::IndexBuffer::uint16);

	m_indexBuffer->bind();
	m_indexBuffer->resize((SlotsCount + 1) * 6);
	m_indexBuffer->unbind();

	m_vertexBuffer = renderer.createVertexBuffer(
		dw::graphics::VertexBuffer::update_often,
		m_vertexFormat);

	m_vertexBuffer->bind();
	m_vertexBuffer->resize((SlotsCount + 1) * 4);
	m_vertexBuffer->unbind();

	updateBuffer();
}


void SpellBar::updateGUI()
{
	const WorldGridManager& worldManager = WorldGridManager::getInstance();
	const MaterialLibrary& materialLib = worldManager.getPlanet()->getMaterialLibrary();
	const ItemMaterialLibrary& itemmaterialLib = worldManager.getPlanet()->getItemMaterialLibrary();

	dw::maths::Vector2f texcoord;


	const dw::system::Window& window = Application::getInstance().getWindow();

	dw::float32 offset = dw::float32(window.getWidth() - ((SlotsCount * SlotDimension) + (SlotsCount - 1) * SlotOffset)) / 2.0f;

	m_root->setPosition(dw::maths::Vector2f(offset,0.0f));
	m_root->deleteChildren();
	m_selecteur.setPosition(dw::maths::Vector2f(dw::float32(m_indexSelecteur * (SlotDimension + SlotOffset)), 0.0f));
	m_root->addChild(& m_selecteur);

	for(dw::uint32 index = 0; index < SlotsCount; ++index)
	{
		Container::Slot slot = m_container->getSlot(index);

		m_imagesBoxes[index].setPosition(dw::maths::Vector2f(dw::float32(index * (SlotDimension + SlotOffset)), 0.0f));
		m_imagesBoxes[index].setDimension(dw::maths::Vector2f(dw::float32(SlotDimension), dw::float32(SlotDimension)));

		if(slot.object.type == Object::BLOC || slot.object.type == Object::ENTITY_BLOC)
		{
			const Material& material = materialLib.getMaterialFromId(slot.object.id);
			texcoord = material.getOffsetTop();

			m_imagesBoxes[index].setImageUV(texcoord,dw::maths::Vector2f(texcoord.x + 1.0f/16.0f, texcoord.y + 1.0f/16.0f));
		}
		else if(slot.object.type == Object::ENTITY)
		{
			m_imagesBoxes[index].setImageUV(dw::maths::Vector2f( 2.0/16.0f, 7.0/16.0f),dw::maths::Vector2f( 3.0/16.0f, 8.0/16.0f));
		}
		else
		{
			m_imagesBoxes[index].setImageUV(dw::maths::Vector2f( 11.0/16.0f, 0.0),dw::maths::Vector2f( 12.0f/16.0f,  1.0f/16.0f));
		}
		
		m_root->addChild(& m_imagesBoxes[index]);
	}


	updateBuffer();
}


void SpellBar::updateBuffer()
{
	std::vector<Widget::UiVertex> vertex;
	std::vector<dw::uint16> index;

	m_trianglesCount = m_root->collectGeometry(&vertex, &index);	

	dwAssert(m_trianglesCount * 3 <= m_indexBuffer->getCount(), "Invalid collection");

	{
		m_indexBuffer->bind();
		m_indexBuffer->write(&index[0]);
		m_indexBuffer->unbind();

		m_vertexBuffer->bind();
		m_vertexBuffer->write(&vertex[0]);
		m_vertexBuffer->unbind();
	}	
}

void SpellBar::indexUp()
{
	m_indexSelecteur++;

	if (m_indexSelecteur >= SlotsCount)
	{
		m_indexSelecteur = 0;
	}
}

void SpellBar::indexDown()
{
	m_indexSelecteur --;

	if (m_indexSelecteur < 0)
	{
		m_indexSelecteur = (SlotsCount - 1);
	}
}

	}//namespace render
} // namespace infinity
